package calculator;

import java.util.Vector;

import Auxiliary.Sequence_CondReact;
import Auxiliary.Sequence_Event;
import Auxiliary.Sequence_Row;
import Auxiliary.Sequence_State;
import Auxiliary.Sequence_StateObserver;
import Auxiliary.Sequence_Value;
import DataView.Action;
import DataView.AttributeInfo;
import DataView.ClassInfo;
import DataView.Expr;
import DataView.OperationInfo;
import DataView.ParameterInfo;
import Store.Attribute;
import Store.Class;
import Store.ClassDiagram;
import Store.CondReact;
import Store.Event;
import Store.Operation;
import Store.Parameter;
import Store.Row;
import Store.State;
import Store.StateObserver;
import Store.StateTable;
import Store.Transition;
import Store.Type;
import Store.UMLEvent;

public class Generator 
{
	
	public static Sequence_Row generateST(Sequence_StateObserver usedSO) 
	{
		Sequence_Row lista = new Sequence_Row();
		
		int max=usedSO.size();
		int massimo[] = new int[max];
		int iterator[] = new int[max];
				
		for (int i=0 ; i<max; i++)
		{
			massimo[i]=usedSO.get(i).getType().values().size();
			iterator[i]=0;
		}
		
		Row temp_row = new Row();
		Sequence_Value temp_list = new Sequence_Value();
		for(int i=0; i<max ; i++)
			temp_list.add(usedSO.get(i).getType().values().get(iterator[i]));
		temp_row.setInfo(temp_list, "impossible", null);		
		lista.add(temp_row);
		for(int pivot=max-1; pivot!=-1 ; )
		{
			iterator[pivot]=(iterator[pivot]+1)%massimo[pivot];
			
			if(iterator[pivot]==0)
				pivot--;
			else 
			{
				pivot=max-1;
				
				temp_row = new Row();
				temp_list = new Sequence_Value();
				for(int i=0; i<max ; i++)
					temp_list.add(usedSO.get(i).getType().values().get(iterator[i]));
				temp_row.setInfo(temp_list, "impossible", null);    
				lista.add(temp_row);
			}
		}
		return lista;
	}

	public static Sequence_StateObserver generateBasicSO(ClassDiagram inputCD, Class context) 
	{
		if(context.getInfo().list_Attribute==null)
			return null;
			
		Sequence_StateObserver lista = new Sequence_StateObserver();
		
		if(context.getInfo().list_Attribute!=null)
			for (Attribute a : context.getInfo().list_Attribute)
		        lista.add(new StateObserver(a.getName(), a.getInfo().getType(), new Expr("")));
		
		return lista;
	}

	public static Sequence_Event generateBasicEV(ClassDiagram aCd, Class context) 
	{
		if(context.getInfo().list_Operation==null)
			return null;
		
		Sequence_Event lista = new Sequence_Event();
		
		if(context.getInfo().list_Operation!=null)
			for (Operation o : context.getInfo().list_Operation)
			{
				Vector<Parameter> p = o.getInfo().getAllParam();
				if(p==null) p= new Vector<Parameter>();
				Sequence_CondReact cr = new Sequence_CondReact();
				CondReact c= new CondReact();
				c.setCondReact(new Expr(""), new Action(""));
				cr.add(c);
				Event e = new Event(o.getName(), p, cr);
				lista.add(e);
			}
		        
		
		return lista;
	}

	public static Sequence_State generateStates(StateTable aSt) 
	{
		Sequence_State temp = new Sequence_State();
		for (Row r : aSt.row.getAll())
		{
			if (r.getName().compareTo("impossible")!=0)
			{
				State aux = new State();
				aux.setInfo(r.getName(), false, false);
				r.setState(aux);
				temp.add(aux);
			}
		}
		return temp;
	}

	public static ClassDiagram generateOutputCD(ClassDiagram aIcd, Sequence_StateObserver aSos, Sequence_Event aEvs) {

		ClassDiagram OCD=aIcd.clone();
		
		for (StateObserver s : aSos.getAll())
		{
			Attribute temp = new Attribute();
			AttributeInfo tempinfo = new AttributeInfo();
			tempinfo.setInfo(s.getName(),OCD.context(), s.getType());
			temp.mkElement(tempinfo);
			if(!OCD.context().hasAttribute(temp))
				OCD.context().getInfo().list_Attribute.add(temp);
		}
		for (Event e : aEvs.getAll())
		{
			Operation optemp = new Operation();
			OperationInfo tempinfo = new OperationInfo();
			tempinfo.setInfo(e.getName(), OCD.context(), e.getInfo().getParameters(),Type.boolean_());
			optemp.mkElement(tempinfo);
			if(!OCD.context().hasOperation(optemp))
				OCD.context().getInfo().list_Operation.add(optemp);
		}
		
		return OCD;
	}
	
	public static Transition generateTransition(State s_temp, Event ev_temp, CondReact cr_temp, Row targetRow) 
	{
		Transition t = new Transition(s_temp, new UMLEvent(ev_temp.getNameDes()), cr_temp.getCondRest(), cr_temp.getReactRest(), targetRow.getState());
		return t;
	}
	
	/*
	public static void main(String Args[])
	{
		Type t = Type.boolean_();
		Enumeration enume = new Enumeration();
		EnumerationInfo ei = new EnumerationInfo();
		Sequence_String lis= new Sequence_String();
		lis.add("ciao");
		lis.add("Salve");
		lis.add("Ossequi");
		ei.setInfo("Saluti", lis);
		enume.mkElement(ei);
		Type e = Type.asType(enume);
		
		StateObserver so1= new StateObserver();
		StateObserver so2= new StateObserver();
		StateObserver so3= new StateObserver();
		StateObserverInfo soi1 = new StateObserverInfo();
		StateObserverInfo soi2 = new StateObserverInfo();
		StateObserverInfo soi3 = new StateObserverInfo();
		soi1.setInfo("so1", t, null);
		soi2.setInfo("so2", e, null);
		soi3.setInfo("so3", t, null);
		so1.mkElement(soi1);
		so2.mkElement(soi2);
		so3.mkElement(soi3);
		
		Sequence_StateObserver sobs = new Sequence_StateObserver();
//		sobs.add(so1);
		sobs.add(so2);
//		sobs.add(so3);
		
		StateTable st_tab = new StateTable();
		st_tab.setROW(generateST(sobs));
		
//		System.out.print(st_tab.vis().getElementAt(0, 0).getName()+" ");
//		System.out.println(st_tab.vis().getElementAt(0, 1).getName());
//		System.out.print(st_tab.vis().getElementAt(1, 0).getName()+" ");
//		System.out.println(st_tab.vis().getElementAt(1, 1).getName());
//		System.out.print(st_tab.vis().getElementAt(2, 0).getName()+" ");
//		System.out.println(st_tab.vis().getElementAt(2, 1).getName());
//		System.out.print(st_tab.vis().getElementAt(3, 0).getName()+" ");
//		System.out.println(st_tab.vis().getElementAt(3, 1).getName());
//		System.out.print(st_tab.vis().getElementAt(4, 0).getName()+" ");
//		System.out.println(st_tab.vis().getElementAt(4, 1).getName());
//		System.out.print(st_tab.vis().getElementAt(5, 0).getName()+" ");
//		System.out.println(st_tab.vis().getElementAt(5, 1).getName());
		
		
	}*/

	
//	public static void main(String Args[])
//	{
//		//passo un null ClassDiagram e una classe(col resto)
//		Class c = new Class();
//		
//		
//		//a mkelement di Class serve un classInfo
//		ClassInfo ci = new ClassInfo();
//		//a setInfo di ClassInfo serve: ((String name, Vector<Operation> operazioni, null))
//		String s = "ClassInfo1";
//		Operation op1 = new Operation();
//		//a mkElement di operation serve un OperationInfo
//		OperationInfo opI1 = new OperationInfo();
//		//a setInfo di OperationInfo serve (String s, null, null, Type t)
//		String s2 = "OperationInfo1";
//		Type t1 = Type.integer();
//		opI1.setInfo(s2, null, null, t1);
//		Operation op2 = new Operation();
//		//a mkElement di operation serve un OperationInfo
//		OperationInfo opI2 = new OperationInfo();
//		//a setInfo di OperationInfo serve (String s, null, null, Type t)
//		String s3 = "OperationInfo2";
//		Type t2 = Type.boolean_();
//		opI2.setInfo(s3, null, null, t2);
//		op1.mkElement(opI1);
//		op2.mkElement(opI2);
//		
//		Vector<Operation> v = new Vector<Operation>();
//		v.add(op1);
//		v.add(op2);
//		
//		ci.setInfo(s, v, null);
//		c.mkElement(ci);
//		
//		if(c.getInfo().list_Operation==null)
//			System.out.println("ma che??");
//		
//		//creo la sequence
//		Sequence_StateObserver l = Generator.generateBasicSO(null, c);
//		if(l==null)
//			System.out.println("NUUUUUUUUUUUUUUUUULLL");
//		if(l!=null)
//			System.out.println("EXISTSSSSSSSSSSSSSSSS");
//	}
	
	public static void main(String args[])
	{
		Class c = new Class();
		//a mkElement di class serve (ClassInfo myInfo)
		ClassInfo classInfo1 = new ClassInfo();
		//a setInfo di classInfo serve (String name, Vector<Operation> operazioni, Vector<Attribute> attributi)
		//STRING 
		String name = "classInfo1";
		
		//VECTOR<OPERATION>
		Vector<Operation> v_operation1 = new Vector<Operation>();
		Operation op1 = new Operation();
		//a mkElement di operation serve (OperationInfo aElIN)
		OperationInfo Oper_info1 = new OperationInfo();
		//a setInfo di operationInfo serve (String s, Class c(null), Vector<Parameter> pars, Type t)
		String OpInfo1_name = "operationInfo1";
		Vector<Parameter> v_param1 = new Vector<Parameter>();
		Parameter p1 = new Parameter();
		// a mkElement di parameter serve (ParameterInfo aElIN)
		ParameterInfo param_info1 = new ParameterInfo();
		//a setInfo di parameterinfo serve (String s, Type t)
		String param_info1_name = "parameter_info1";
		Type t1 = Type.boolean_();
		param_info1.setInfo(param_info1_name, t1);
		p1.mkElement(param_info1);
		v_param1.add(p1);
		Type t2 = Type.boolean_();
		Oper_info1.setInfo(OpInfo1_name, null, v_param1, t2);
		op1.mkElement(Oper_info1);
		v_operation1.add(op1);
		
		
		//VECTOR<ATTRIBUTE>
		Vector<Attribute> v_attr1 = new Vector<Attribute>();
		Attribute a1 = new Attribute();
		//a mkelement di attribute serve un attributeinfo
		AttributeInfo att1 = new AttributeInfo();
		//a setInfo di attributeinfo serve (String name, null, Type type)
		String attr_info_name = "attInfo1";
		Type t3 = Type.real();
		att1.setInfo(attr_info_name, null, t3);
		a1.mkElement(att1);
		v_attr1.add(a1);
		
		classInfo1.setInfo(name, v_operation1, v_attr1);
		c.mkElement(classInfo1);
		
		
		//(dalle operation passate vengono creati gli eventi)
		Sequence_Event seq = Generator.generateBasicEV(null, c);	
		
		System.out.println(seq.get(0).getInfo().getParameters().get(0).getInfo().getName());
		System.out.println(seq.get(0).getInfo().getParameters().get(0).getInfo().getType().getName());
		
		
	}
	
	
	
	
}